
package l1j.server.GameServer;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.Socket;
import java.net.URL;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.HashMap;
import java.util.TimeZone;
import java.util.logging.Level;
import java.util.logging.Logger;














import l1j.opqlo.AutoPay.AutoPayModel;
import l1j.opqlo.List.OnlineUser;
import l1j.opqlo.List.特殊列表;
import l1j.opqlo.NewSystem.ChatLog;
import l1j.opqlo.NewSystem.PlayHamster;
import l1j.opqlo.NewSystem.goblinThread;
import l1j.opqlo.NewSystem.刮刮樂;
import l1j.opqlo.NewSystem.各項記錄輸出;
import l1j.opqlo.NewSystem.Attack.L1AttackList;
import l1j.opqlo.NewSystem.Extension.CrackTime;
import l1j.opqlo.NewSystem.Extension.TreasureMaster;
import l1j.opqlo.NewSystem.Extension.FireRoom.FireRoomThread;
import l1j.opqlo.NewSystem.ItemLevelUp.ItemLevelUpTable;
import l1j.opqlo.NewSystem.LABA.LabaTable;
import l1j.opqlo.NewSystem.Play18La.Play18La;
import l1j.opqlo.NewSystem.鑑定系統.IdentifiedTable;
import l1j.opqlo.Server.CmdEcho;
import l1j.opqlo.Server.Data.WeaponArmorLevelUp;
import l1j.opqlo.Server.L1World.L1World;
import l1j.opqlo.Server.L1World.WorldCrown;
import l1j.opqlo.Server.L1World.WorldDarkelf;
import l1j.opqlo.Server.L1World.WorldDragonKnight;
import l1j.opqlo.Server.L1World.WorldElf;
import l1j.opqlo.Server.L1World.WorldIllusionist;
import l1j.opqlo.Server.L1World.WorldKnight;
import l1j.opqlo.Server.L1World.WorldPet;
import l1j.opqlo.Server.L1World.WorldSummons;
import l1j.opqlo.Server.L1World.WorldWizard;
import l1j.opqlo.Timer.Controler.PcTimerControler;
import l1j.opqlo.Timer.Controler.Server.ServerWarTimer;
import l1j.opqlo.Timer.NpcControler.NpcTimerControler;
import l1j.opqlo.假人系統.A_DummyTable;
import l1j.opqlo.假人系統.DummyThread;
import l1j.opqlo.假人系統.RobotTable;
import l1j.opqlo.移民.checkTable;
import l1j.opqlo.移民.checkThread;
import l1j.server.AinTimeController;
import l1j.server.Config;
import l1j.server.DatabaseFactory;
import l1j.server.Thread.GeneralThreadPool;
import l1j.server.Thread.NpcAiThreadPool;
import l1j.server.Thread.PcOtherThreadPool;
import l1j.server.echo.ClientThread;
import l1j.server.server.Announcecycle;
import l1j.server.server.Announcements;
import l1j.server.server.AuctionTimeController;
import l1j.server.server.FishingTimeController;
import l1j.server.server.GMCommandsConfig;
import l1j.server.server.GetNowTime;
import l1j.server.server.HomeTownTimeController;
import l1j.server.server.HouseTaxTimeController;
import l1j.server.server.IdFactory;
import l1j.server.server.LightTimeController;
import l1j.server.server.NpcChatTimeController;
import l1j.server.server.Shutdown;
import l1j.server.server.datatables.CastleTable;
import l1j.server.server.datatables.CharObjidTable;
import l1j.server.server.datatables.CharacterTable;
import l1j.server.server.datatables.DecomposeTable;
import l1j.server.server.datatables.DoorSpawnTable;
import l1j.server.server.datatables.DropItemTable;
import l1j.server.server.datatables.DropTable;
import l1j.server.server.datatables.ExpTable;
import l1j.server.server.datatables.FurnitureSpawnTable;
import l1j.server.server.datatables.FusionTable;
import l1j.server.server.datatables.GetBackRestartTable;
import l1j.server.server.datatables.IpTable;
import l1j.server.server.datatables.ItemTable;
import l1j.server.server.datatables.MailTable;
import l1j.server.server.datatables.MapsTable;
import l1j.server.server.datatables.MobGroupTable;
import l1j.server.server.datatables.NPCTalkDataTable;
import l1j.server.server.datatables.NpcActionTable;
import l1j.server.server.datatables.NpcChatTable;
import l1j.server.server.datatables.NpcSpawnTable;
import l1j.server.server.datatables.NpcTable;
import l1j.server.server.datatables.PetTable;
import l1j.server.server.datatables.PetTypeTable;
import l1j.server.server.datatables.PolyTable;
import l1j.server.server.datatables.RaceTicketTable;
import l1j.server.server.datatables.ResolventTable;
import l1j.server.server.datatables.ShopTable;
import l1j.server.server.datatables.SkillsTable;
import l1j.server.server.datatables.SpawnTable;
import l1j.server.server.datatables.SprTable;
import l1j.server.server.datatables.WeaponSkillTable;
import l1j.server.server.model.BeginnerTable;
import l1j.server.server.model.Dungeon;
import l1j.server.server.model.ElementalStoneGenerator;
import l1j.server.server.model.Getback;
import l1j.server.server.model.L1BossCycle;
import l1j.server.server.model.L1CastleLocation;
import l1j.server.server.model.L1DeleteItemOnGround;
import l1j.server.server.model.L1Location;
import l1j.server.server.model.Instance.L1PcInstance;
import l1j.server.server.model.game.L1BugBearRace;
import l1j.server.server.model.gametime.L1GameTimeClock;
import l1j.server.server.model.item.L1TreasureBox;
import l1j.server.server.model.map.L1WorldMap;
import l1j.server.server.model.trap.L1WorldTraps;
import l1j.server.server.serverpackets.S_Disconnect;
import l1j.server.server.utils.PerformanceTimer;
import l1j.server.server.utils.Random;
import l1j.server.server.utils.SQLUtil;
import l1j.server.server.utils.StreamUtil;
import l1j.server.server.datatables.MonsterEnhanceTable;//TODO 怪物強化系統by missu0524
import l1j.eric.RandomMobTable;//TODO 新增怪物隨機地圖產生 by eric1300460
import l1j.eric.StartCheckWarTime;//TODO 修正攻城時間如果不是比現在時間久無法更新錯誤 by eric1300460
import l1j.william.ItemSummon;//TODO 召喚道具
import l1j.william.L1GameReStart;//TODO 伺服器自動重啟 by 阿傑
import l1j.server.server.datatables.MagicDollTable;//TODO 魔法娃娃DB化
import l1j.server.server.datatables.lock.AccountReading;
import l1j.server.server.datatables.lock.CharItemsReading;
import l1j.server.server.datatables.lock.CharSkillReading;
import l1j.server.server.datatables.lock.CharacterConfigReading;
import l1j.server.server.datatables.lock.ClanEmblemReading;
import l1j.server.server.datatables.lock.ClanReading;
import l1j.server.server.datatables.lock.GameConfigReading;
import l1j.server.server.datatables.lock.HellTimeReading;

public class GameServer{

	private class ServerShutdownThread extends Thread {
		private final int _secondsCount;

		public ServerShutdownThread(final int secondsCount) {
			this._secondsCount = secondsCount;
		}

		@Override
		public void run() {
			final L1World world = L1World.getInstance();
			try {
				int secondsCount = this._secondsCount;
				world.broadcastServerMessage("伺服器即將關閉。");
				world.broadcastServerMessage("請玩家移動到安全區域先行登出");
				while (0 < secondsCount) {
					if (secondsCount <= 30) {
						world.broadcastServerMessage("伺服器將在" + secondsCount+ "秒後關閉，請玩家移動到安全區域先行登出。");
						_log.log(Level.SEVERE, "伺服器將於 " + secondsCount +" 秒後重新啟動");
						if(Config.BugbearRace_Switch){
							L1BugBearRace.getInstance().ServerReStart();//opqlo 賭肥
							Config.BugbearRace_Switch=false;
						}
						Play18La.get().StopGame();
					} else {
						if (secondsCount % 60 == 0) {
							world.broadcastServerMessage("伺服器將在" + secondsCount/ 60 + "分鐘後關閉。");
							_log.log(Level.SEVERE, "伺服器將於 " + secondsCount/60 +" 分鐘後重新啟動");
						}
					}
					Thread.sleep(1000);
					secondsCount--;
				}
				GameServer.this.shutdown();
			} catch (final InterruptedException e) {
				world.broadcastServerMessage("已取消伺服器關機。伺服器將會正常運作。");
				return;
			}
		}
	}
	private static Logger _log = Logger.getLogger(GameServer.class.getName());
	private static int YesNoCount = 0;//TODO 3.51C封包還需要在測試

	private int chatlvl;



	private static GameServer _instance;


	/**
	 * 踢掉世界地圖中所有的玩家與儲存資料。
	 */
	private static boolean _isMsg = false;

	private static final HashMap<ClientThread , L1PcInstance> _ClientPc = new HashMap<ClientThread , L1PcInstance>(2000);
	public static GameServer getInstance() {
		if (_instance == null) {
			_instance = new GameServer();
		}
		return _instance;
	}
	/**
	 *3.51C封包還需要在測試
	 *@return
	 */
	public static int getYesNoCount() {
		YesNoCount += 1;
		return YesNoCount;
	}
	private ServerShutdownThread _shutdownThread = null;

	private final ArrayList<L1Location>_mobList = new ArrayList<L1Location>();


	public synchronized void abortShutdown() {
		if (this._shutdownThread == null) {
			// シャットダウン要求が行われていない
			// TODO エラー通知が必要かもしれない
			return;
		}

		this._shutdownThread.interrupt();
		this._shutdownThread = null;
	}

	public void addLogMob(L1Location loc){
		this._mobList.add(loc);
	}


	public void addOnlinePc(final ClientThread client , final L1PcInstance pc){
		_ClientPc.put(client, pc);
	}

	public void clearOnlinePc(){
		_ClientPc.clear();
	}
	private boolean isClose = false;
	public void disconnectAllCharacters() {
		//		try{
		//			UpdateLight(false);//關閉伺服器燈號
		//		}catch(Exception e){
		//
		//		}
		try{
			Play18La.get().StopGame();//回存所有玩家的下注。
		}catch(Exception e){}
		RaceTicketTable.getInstance().ServerReStart(L1BugBearRace.getInstance().getRound());
		L1World.getInstance().broadcastPacketToAll(new S_Disconnect());
		try {
			final Collection<ClientThread> list = OnlineUser.get().all();
			if (!_isMsg) {
				LabaTable.getInstance().setLabaData();//opqlo 關機時拉霸記錄
				this.saveLogMob();
				刮刮樂.getInstance().saveTheTotalCount();
				//對話紀錄
				ChatLog.get().ChatLogSave();
				_isMsg = true;
				_log.info("人物/物品 資料的存檔 - 關閉核心前連線帳號數量: " + list.size());
			}
			for (final ClientThread client : list) {
				try {
					client.close();
				} catch (final Exception e) {
					_log.log(Level.SEVERE , e.getLocalizedMessage() , e);
				}
			}
		} catch (final Exception e) {
			_log.log(Level.SEVERE , e.getLocalizedMessage() , e);
		}
		if(Config.SERVERCE !=9999){
			if(!isClose){
				isClose = true;
				if(Config.SERVERCE ==1){
					try {
						stopFirstServer();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}//關閉驗證伺服器
					startBrigeServer("192.168.1.111" , 6262);//關閉橋接伺服器
					startBrigeServer("192.168.1.112" , 6262);//關閉橋接伺服器	
					startBrigeServer("192.168.1.113" , 6262);//關閉橋接伺服器
				}else if(Config.SERVERCE == 3){
					startBrigeServer("192.168.1.111" , 6263);//關閉橋接伺服器
					startBrigeServer("192.168.1.112" , 6263);//關閉橋接伺服器	
					startBrigeServer("192.168.1.113" , 6263);//關閉橋接伺服器
				}
			}
		}
	}

	private int id = 0;

	private void getMaxId(){
		Connection con = null;
		PreparedStatement pstm = null;
		ResultSet rs = null;
		try {
			con = DatabaseFactory.get().getConnection();
			pstm = con.prepareStatement("select id from spawnlist_npc order by id DESC limit 0,1;");
			rs = pstm.executeQuery();
			if (rs.next()) {
				this.id = rs.getInt("id")+1;
			}
		} catch (final Exception e) {

			_log.log(Level.WARNING , e.getLocalizedMessage());
		} finally {
			SQLUtil.close(rs ,pstm , con);
		}
	}
	public int getOnlineClientMapSize(){
		return _ClientPc.size();
	}
	public L1PcInstance getOnlinePc(final ClientThread client){
		return _ClientPc.get(client);
	}
	public void initialize() throws Exception {
		final PerformanceTimer timer = new PerformanceTimer();
		try{
			loadCharacters();
			// 客戶端封包資料加載
			//			PacketHandler.load();

			CharObjidTable.get().load();// 人物已用OBJID預先加載/血盟已用OBJID預先加載

			final double rateXp = Config.RATE_XP;
			final double LA = Config.RATE_LA;
			final double rateKarma = Config.RATE_KARMA;
			final double rateDropItems = Config.RATE_DROP_ITEMS;
			final double rateDropAdena = Config.RATE_DROP_ADENA;
			final int l = Config.ENCHANT_CHANCE_WEAPON;
			final int m = Config.ENCHANT_CHANCE_ARMOR;
			//final String slang = Config.CLIENT_LANGUAGE_CODE;

			this.chatlvl = Config.GLOBAL_CHAT_LEVEL;
			//伺服器輸出語言: " + (slang)+"\n伺服器介面【" + clentLanguage() + "】
			final StringBuilder ServerMessage = new StringBuilder();

			ServerMessage
			.append("經驗值: ").append(rateXp)
			.append("倍\n掉寶率: ").append(rateDropItems)
			.append("倍\n取得金幣: ").append(rateDropAdena)
			.append("倍\n衝武器 / 防具機率: ").append(l).append("% / ").append(m)
			.append("%\n全體頻道可使用等級 Lv.").append(this.chatlvl)
			.append("級\n正義值: ").append(LA)
			.append("倍 \n友好度: ").append(rateKarma)
			.append("倍\n殺人設定：【").append(Config.ALT_NONPVP)
			.append("】 \n轉生藥水取得：").append(Config.ALT_REVIVAL_POTION)
			.append("\n 轉生血魔保留： ").append(Config.REVIVAL_POTION*10)
			.append("%\n");
			this.clearOnlinePc(); //opqlo 防卡登
			if(Config.MAX_ONLINE_USERS >0){
				ServerMessage
				.append("連線人數限制：").append(Config.MAX_ONLINE_USERS).append("人\n");
			}

			DropTable.getInstance();
			IdFactory.getInstance();
			L1WorldMap.getInstance();// 地圖設置
			CharacterTable.getInstance().loadAllCharName();// 載入已用名稱
			CharacterTable.clearOnlineStatus();// 全部狀態離線

			// ゲーム時間時計
			L1GameTimeClock.init();
			//TODO 伺服器自動重啟 by阿傑
			if (Config.REST_TIME > 0) {
				L1GameReStart.init();
			}
			/*	// UBタイムコントローラー 無限大戰
		final UbTimeController ubTimeContoroller = UbTimeController.getInstance();
		GeneralThreadPool.getInstance().execute(ubTimeContoroller);
			 */
			// 戦争タイムコントローラー
			//		final ServerWarExecutor warTimeController = ServerWarExecutor.get();
			//		GeneralThreadPool.getInstance().execute(warTimeController);

			CastleTable.getInstance();// 城堡資料
			ClanReading.get().load();// 血盟資料

			ClanEmblemReading.get().load();// 血盟盟徽資料

			PcOtherThreadPool.get();// 線程工廠設置

			NpcAiThreadPool.get();// 線程工廠設置

			GeneralThreadPool.getInstance();// 線程工廠設置

			// 城戰計時軸
			final ServerWarTimer warTimer = new ServerWarTimer();
			warTimer.start();


			// 精霊の石生成
			if (Config.ELEMENTAL_STONE_AMOUNT > 0) {
				final ElementalStoneGenerator elementalStoneGenerator = ElementalStoneGenerator.getInstance();
				GeneralThreadPool.getInstance().execute(elementalStoneGenerator);
			}

			// ホームタウン
			HomeTownTimeController.getInstance();

			// アジト競売タイムコントローラー
			final AuctionTimeController auctionTimeController = AuctionTimeController.getInstance();
			GeneralThreadPool.getInstance().execute(auctionTimeController);

			// アジト税金タイムコントローラー
			final HouseTaxTimeController houseTaxTimeController = HouseTaxTimeController.getInstance();
			GeneralThreadPool.getInstance().execute(houseTaxTimeController);

			// 初始化釣魚
			final FishingTimeController fishingTimeController = FishingTimeController.getInstance();
			//GeneralThreadPool.getInstance().execute(fishingTimeController);
			fishingTimeController.start();

			// NPCチャットタイムコントローラー
			final NpcChatTimeController npcChatTimeController = NpcChatTimeController.getInstance();
			GeneralThreadPool.getInstance().execute(npcChatTimeController);

			// ライトタイムコントローラー
			final LightTimeController lightTimeController = LightTimeController.getInstance();
			GeneralThreadPool.getInstance().execute(lightTimeController);

			// TODO 殷海薩的祝福
			final AinTimeController ainTimeController = AinTimeController.getInstance();
			GeneralThreadPool.getInstance().execute(ainTimeController);

			Announcements.getInstance();
			// 循環公告 by阿傑
			if (Config.Use_Show_Announcecycle) {
				Announcecycle.getInstance();
			}
			NpcTable.getInstance();
			//TODO 怪物強化系統
			MonsterEnhanceTable.getInstance();
			//TODO 怪物強化系統
			final L1DeleteItemOnGround deleteitem = new L1DeleteItemOnGround();
			deleteitem.initialize();

			if (!NpcTable.getInstance().isInitialized()) {
				throw new Exception("Could not initialize the npc table");
			}

			/**鑑定系統相關*/
			IdentifiedTable.getInstance().loadTable();
			IdentifiedTable.getInstance().load();

			/**經驗相關數值讀取*/
			ExpTable.getInstance().load();

			/** 客戶端封包資料加載*/
			//PacketHandler.load();
			/**特殊列表加載*/
			特殊列表.get().load();

			L1AttackList.load();
			//		AutoShopTable.getInstance().loadDate();//opqlo 寄賣系統
			//			Place.getInstance().load();//opqlo 伺服器排名
			ItemLevelUpTable.getInstance();//opqlo 道具升級系統
			SpawnTable.getInstance();
			MobGroupTable.getInstance();
			PolyTable.getInstance();
			ItemTable.getInstance();
			AccountReading.get().load();// 帳戶名稱資料
			// 背包資料建立
			CharItemsReading.get().load();

			BeginnerTable.get().load();// 新手物品資料
			SkillsTable.getInstance().load();// 技能設置資料
			// 人物技能紀錄
			CharSkillReading.get().load();

			// 人物快速鍵紀錄
			CharacterConfigReading.get().load();

			// 神恩特殊控制項目紀錄
			GameConfigReading.get().load();

			DropItemTable.getInstance();
			ShopTable.getInstance();
			NPCTalkDataTable.getInstance();
			L1World.getInstance();
			WorldCrown.get();

			WorldKnight.get();

			WorldElf.get();

			WorldWizard.get();

			WorldDarkelf.get();

			WorldDragonKnight.get();

			WorldIllusionist.get();

			WorldPet.get();

			WorldSummons.get();

			L1WorldTraps.getInstance();

			Dungeon.getInstance();
			NpcSpawnTable.getInstance();
			IpTable.getInstance();
			MapsTable.getInstance();
			//		UBSpawnTable.getInstance();
			PetTable.getInstance();
			StartCheckWarTime.getInstance();//TODO 修正攻城時間如果不是比現在時間久無法更新錯誤 by eric1300460
			L1CastleLocation.setCastleTaxRate(); // これはCastleTable初期化後でなければいけない
			GetBackRestartTable.getInstance();
			DoorSpawnTable.getInstance();

			//ChatLogTable.getInstance();
			WeaponSkillTable.getInstance();
			ItemSummon.getInstance();//TODO 召喚道具
			NpcActionTable.load();
			GMCommandsConfig.load();
			Getback.loadGetBack();
			PetTypeTable.load();
			L1BossCycle.load();
			L1TreasureBox.load();
			SprTable.getInstance();
			ResolventTable.getInstance();
			FurnitureSpawnTable.getInstance();
			NpcChatTable.getInstance();
			MailTable.getInstance();
			MagicDollTable.getInstance();//TODO 魔法娃娃DB化
			//TODO 開始怪物隨機出生點
			RandomMobTable.getInstance().startRandomMob();
			/**賽肥 OPQLO*/
			RaceTicketTable.getInstance();
			L1BugBearRace.getInstance();
			ServerMessage.append("----------拉霸彩金記錄讀取中-----------\n");


			/**oplqo 對話記錄*/
			//	ChatLog.get();
			/**opqlo 時空裂痕計時*/
			CrackTime.get();

			/**opqlo 多種計時器啟動*/
			new PcTimerControler().Load();
			new NpcTimerControler().Load();

			/**opqlo伺服器資訊整合*/
			System.out.println(ServerMessage.toString());
			ServerMessage.delete(0, ServerMessage.length());
			/**opqlo伺服器資訊整合*/

			RobotTable.getInstance().load();
			A_DummyTable.get().loadNpc();
			A_DummyTable.get().load();//假人掛賣
			A_DummyTable.get().load_shop();
			PlayHamster.getIntance();//打地鼠
			DummyThread.getInstance().start();
			//			O_RobotTimer.get().start();
			//			new DummyThread().start(); 
			LabaTable.getInstance();//opqlo 拉霸系統
			//NewYear.getInstance(); //opqlo 紅包排名
			AutoPayModel.getInstance().start();//自動贊助
			WeaponArmorLevelUp.getInstance();//武防升級轉換作業

			HellTimeReading.get().load();//地獄保釋官
			//			MapPointCheck.get().check();//地圖大小計算
			DecomposeTable.get().load();//物品拆解
			FusionTable.get().load();//物品合成
			if(Config.IS_ON_ATTACK){
				final LanSecurityManager manager = new LanSecurityManager();
				manager.stsrt_cmd_tmp();
			}
			各項記錄輸出.setLocation();//創建紀錄需要的資料夾
			new 各項記錄輸出().startLog();
			System.out.println("---------------------------------------\n\n\n\n\n	《***************** 資 料 庫 全 數 加 載 完 畢 *****************》");
			Runtime.getRuntime().addShutdownHook(Shutdown.getInstance());

			Thread.sleep(1000);
			if(Config.MIGRATE){
				System.out.println("移民系統開始運作!!!!");
				checkTable.get();
				new checkThread().start();
			}
			Play18La.get();//骰寶
			FireRoomThread.get();//殞鳳副本管理器初始化
			//			UpdateLight(true);//開啟伺服器燈號
			// 監聽端口啟動重置作業
			EchoServerTimer.get().start();
				if(Config.SERVERCE == 1){
					startFirstServer();//開啟驗證伺服器
					startBrigeServer("192.168.1.111" , 6262);//開啟橋接伺服器
					startBrigeServer("192.168.1.112" , 6262);//開啟橋接伺服器
					startBrigeServer("192.168.1.113" , 6262);//開啟橋接伺服器
				}else if(Config.SERVERCE == 3){
					startBrigeServer("192.168.1.111" , 6263);//開啟橋接伺服器
					startBrigeServer("192.168.1.112" , 6263);//開啟橋接伺服器
					startBrigeServer("192.168.1.113" , 6263);//開啟橋接伺服器
			}
				
				goblinThread.getInstance().start();
//				while(true){
//				ArrayList<Integer>_allMap = new ArrayList<Integer>();
//				ArrayList<Integer>_tempList = new ArrayList<Integer>();
//
//				_allMap.add(604	);
//				_allMap.add(605	);
//				_allMap.add(606	);
//				_allMap.add(607	);
//				_allMap.add(6321	);
//				_allMap.add(9901	);
//				_allMap.add(9914	);
//				_allMap.add(9915	);
//				_allMap.add(9916	);
//				_allMap.add(9918	);
//				_allMap.add(9919	);
//				_allMap.add(9920	);
//				_allMap.add(9921	);
//				_allMap.add(9922	);
//				_allMap.add(9923	);
//				_allMap.add(9991	);
//				_allMap.add(9992	);
//				_allMap.add(9993	);
//				_allMap.add(9994	);
//				_allMap.add(9995);
//				while(_tempList.size() <10){
//					final int rate = Random.nextInt(_allMap.size());
//					_tempList.add(_allMap.get(rate));
//					_allMap.remove(rate);
//				}
//				for(int i= _tempList.size()-1 ; i>=0; i--){
//					final int mapId = _tempList.get(i);
//					System.out.print(mapId+"、");
//				}
//				System.out.println("-----------------------");
//				_allMap.addAll(_tempList);
//				_tempList.clear();
//				Thread.sleep(5000);
//				}
				
			//			new RobotThread().start();

			//			new NioServer(5091); 
			//			l1j.opqlo.NewSystem.TEST tt = new l1j.opqlo.NewSystem.TEST();
			//			tt.start();

			//		ServerExecutor
			//		System.out.println("\n\n\n伺服器狀態 >> 伺服器啟動");
			//			final HashMap<String , Integer> list = new HashMap<String , Integer>();
			//			for(int i=0; i<1000; i++){
			//				final L1TreasureBox box = L1TreasureBox.get(610012);
			//				if (box != null) {
			//					final L1ItemInstance item =box.testBox();
			//					if(list.containsKey(item.getLogName())){
			//						 int count =list.get(item.getLogName());
			//						 list.put(item.getLogName(), count+1);
			//					}else{
			//						 list.put(item.getLogName(), 1);
			//					}
			//				}
			//			}
			//			Set<String>key =list.keySet();
			//			Iterator<String>key2 = key.iterator();
			//			while(key2.hasNext()){
			//			String name = key2.next();
			//			_log.info("\r\n"+name+"	"+list.get(name));
			//			}
			//			
		}catch (final IOException e) {
			_log.log(Level.SEVERE , e.getLocalizedMessage() , e);
		}
		// 啟動視窗命令接收器
		final CmdEcho cmdEcho = new CmdEcho(timer.get());
		cmdEcho.runCmd();
	}

	public void removeOnlinePc(final ClientThread client){
		_ClientPc.remove(client);
	}
	private void saveLogMob(){
		各項記錄輸出.setAllLog();
		if(this._mobList.isEmpty()){
			return;
		}
		this.getMaxId();
		System.out.println("卡點青蛙儲存中.....");
		for(int i=0; i<this._mobList.size(); i++){
			final L1Location loc = this._mobList.get(i);
			Connection con = null;
			PreparedStatement pstm = null;
			try {
				con = DatabaseFactory.get().getConnection();
				pstm = con.prepareStatement("INSERT INTO spawnlist_npc SET id=?, location=?,count=?,npc_templateid=?,locx=?,locy=?,heading=?,mapid=?");
				pstm.setInt(1, this.id);
				pstm.setString(2, "卡點青蛙");
				pstm.setInt(3, 1);
				pstm.setInt(4, 710049);
				pstm.setInt(5, loc.getX());
				pstm.setInt(6, loc.getY());
				pstm.setInt(7, 0);
				pstm.setInt(8, loc.getMapId());
				pstm.execute();
				this.id++;
			} catch (final Exception e) {
				_log.log(Level.WARNING , e.getLocalizedMessage());
			} finally {
				SQLUtil.close(pstm ,con);
			}
		}
		this._mobList.clear();
		System.out.println("卡點青蛙儲存儲存完畢!!!!");
	}

	public void shutdown() {
		this.disconnectAllCharacters();
		System.exit(0);
	}
	public synchronized void shutdownWithCountdown(final int secondsCount) {
		if (this._shutdownThread != null) {
			// 既にシャットダウン要求が行われている
			// TODO エラー通知が必要かもしれない
			return;
		}
		this._shutdownThread = new ServerShutdownThread(secondsCount);
		GeneralThreadPool.getInstance().execute(this._shutdownThread);
	}

	/* try {
		    URL myURL = new URL(e5);
		    URLConnection myURLConnection = myURL.openConnection();
		    myURLConnection.connect();
		    System.out.println(myURLConnection.getInputStream().available());
//		    myURLConnection.getInputStream().available();
		}
		catch (MalformedURLException e) {
		    // new URL() failed
		    // ...
		}
		catch (IOException e) {
		    // openConnection() failed
		    // ...
		}*/
	//	private void sqqq(){
	//		try {
	//			sss();
	//			for(L1PcInstance pc : _pcll){
	//				CopyOnWriteArrayList<L1ItemInstance> _items= CharItemsReading.get().loadItems(pc.getId());
	//				if(_items !=null){
	//					for(final L1ItemInstance item : _items){
	//						if(item.getEnchantLevel() >0){
	//							final int itemid = item.getItemId();
	//							int newid =0;
	//							switch(itemid){
	//							case 643:
	//								newid = 648;
	//								break;
	//							case 651:
	//								newid = 656;
	//								break;
	//							case 659:
	//								newid = 664;
	//								break;
	//							case 667:
	//								newid = 672;
	//								break;
	//							case 675:
	//								newid = 680;
	//								break;
	//							}
	//							if(newid !=0){
	//								StringBuilder log = new StringBuilder();
	//								log.append("玩家:").append(pc.getName()).append(" 武器:").append(item.getLogName()).append(" 轉換成 ");
	//								item.setItemId(newid);
	//								final L1Item template = ItemTable.getInstance().getTemplate(item.getItemId());
	//								item.setItem(template);
	//								updateGive(item.getId() , newid);
	//								log.append(item.getLogName());
	//								System.out.println(log.toString());
	//							}
	//						}
	//					}
	//				}
	//			}
	//		}catch(Exception e){
	//			_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
	//		}
	//	}
	//
	//	private static final ArrayList<L1PcInstance>_pcll = new ArrayList<L1PcInstance>();
	//
	//	private void sss(){
	//		Connection con = null;
	//		PreparedStatement pstm = null;
	//		ResultSet rs = null;
	//		L1PcInstance pc = null;
	//		try {
	//
	//			con = DatabaseFactory.get().getConnection();
	//			pstm = con.prepareStatement("SELECT * FROM characters WHERE TYPE=?");
	//			pstm.setInt(1, 4);
	//			rs = pstm.executeQuery();
	//			while(rs.next()){
	//				pc = new L1PcInstance();
	//				pc.setAccountName(rs.getString("account_name"));
	//				pc.setId(rs.getInt("objid"));
	//				pc.setName(rs.getString("char_name"));
	//				//TODO 角色誕生by99團隊
	//				pc.setBirthday(rs.getTimestamp("birthday"));
	//				//TODO 角色誕生by99團隊
	//				pc.setHighLevel(rs.getInt("HighLevel"));
	//				pc.setExp(rs.getInt("Exp"));
	//				pc.addBaseMaxHp(rs.getInt("MaxHp"));
	//				pc.setCurrentHpDirect(rs.getInt("CurHp"));
	//				pc.setDead(false);
	//				pc.setStatus(0);
	//				pc.addBaseMaxMp(rs.getShort("MaxMp"));
	//				pc.setCurrentMpDirect(rs.getShort("CurMp"));
	//				//opqlo 七屬性破127
	//				pc.addBaseStr(rs.getShort("Str"));
	//				pc.addBaseCon(rs.getShort("Con"));
	//				pc.addBaseDex(rs.getShort("Dex"));
	//				pc.addBaseCha(rs.getShort("Cha"));
	//				pc.addBaseInt(rs.getShort("Intel"));
	//				pc.addBaseWis(rs.getShort("Wis"));
	//				//opqlo 七屬性破127
	//				int status = rs.getInt("Status");
	//				pc.setCurrentWeapon(status);
	//				int classId = rs.getInt("Class");
	//				pc.setClassId(classId);
	//				pc.setTempCharGfx(classId);
	//				pc.setGfxId(classId);
	//				pc.set_sex(rs.getInt("Sex"));
	//				pc.setType(rs.getInt("Type"));
	//				int head = rs.getInt("Heading");
	//				if (head > 7) {
	//					head = 0;
	//				}
	//				pc.setHeading(head);
	//				pc.setX(rs.getInt("locX"));
	//				pc.setY(rs.getInt("locY"));
	//				pc.setMap(rs.getShort("MapID"));
	//				pc.set_food(rs.getInt("Food"));
	//				pc.setLawful(rs.getInt("Lawful"));
	//				pc.setTitle(rs.getString("Title"));
	//				pc.setClanid(rs.getInt("ClanID"));
	//				pc.setClanname(rs.getString("Clanname"));
	//				pc.setClanRank(rs.getInt("ClanRank"));
	//				pc.setBonusStats(rs.getInt("BonusStatus"));
	//				pc.setElixirStats(rs.getInt("ElixirStatus"));
	//				pc.setElfAttr(rs.getInt("ElfAttr"));
	//				pc.set_PKcount(rs.getInt("PKcount"));
	//				pc.setPkCountForElf(rs.getInt("PkCountForElf"));
	//				pc.setExpRes(rs.getInt("ExpRes"));
	//				pc.setPartnerId(rs.getInt("PartnerID"));
	//				pc.setAccessLevel(rs.getShort("AccessLevel"));
	//				if (pc.getAccessLevel() == 200) {
	//					pc.setGm(true);
	//					pc.setMonitor(false);
	//					pc.allopen();
	//				} else if (pc.getAccessLevel() == 100) {
	//					pc.setGm(false);
	//					pc.setMonitor(true);
	//				} else {
	//					pc.setGm(false);
	//					pc.setMonitor(false);
	//				}
	//				pc.setOnlineStatus(rs.getInt("OnlineStatus"));
	//				pc.setHomeTownId(rs.getInt("HomeTownID"));
	//				pc.setContribution(rs.getInt("Contribution"));
	//				pc.setHellTime(rs.getInt("HellTime"));
	//				pc.setBanned(rs.getBoolean("Banned"));
	//				pc.setKarma(rs.getInt("Karma"));
	//				pc.set_metempsychosis(rs.getInt("metempsychosis"));//TODO 記錄轉生次數
	//				pc.setLastPk(rs.getTimestamp("LastPk"));
	//				pc.setLastPkForElf(rs.getTimestamp("LastPkForElf"));
	//				pc.setDeleteTime(rs.getTimestamp("DeleteTime"));
	//				pc.setOriginalStr(rs.getInt("OriginalStr"));
	//				pc.setOriginalCon(rs.getInt("OriginalCon"));
	//				pc.setOriginalDex(rs.getInt("OriginalDex"));
	//				pc.setOriginalCha(rs.getInt("OriginalCha"));
	//				pc.setOriginalInt(rs.getInt("OriginalInt"));
	//				pc.setOriginalWis(rs.getInt("OriginalWis"));
	//				pc.setLastActive(rs.getTimestamp("LastActive"));// TODO 殷海薩的祝福
	//				pc.setAinZone(rs.getInt("AinZone"));// TODO 殷海薩的祝福
	//				pc.setAinPoint(rs.getInt("AinPoint"));// TODO 殷海薩的祝福
	//				pc.refresh();
	//				pc.setMoveSpeed(0);
	//				pc.setBraveSpeed(0);
	//				pc.setGmInvis(false);
	//				_pcll.add(pc);
	//			}
	//		} catch (SQLException e) {
	//			_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
	//		} finally {
	//			SQLUtil.close(rs , pstm , con);
	//		}
	//	}
	//
	//	private void updateGive(final int id , final int newid) {
	//
	//		Connection con = null;
	//		PreparedStatement pstm = null;
	//		try {
	//			con = DatabaseFactory.get().getConnection();
	//			pstm = con
	//					.prepareStatement("UPDATE character_items SET item_id = ?, is_equipped=? WHERE id = ?");
	//			pstm.setInt(1, newid);
	//			pstm.setInt(2, 0);
	//			pstm.setInt(3, id);
	//			pstm.execute();
	//		} catch (final Exception e) {
	//			_log.log(Level.SEVERE, "ブックマークの削除でエラーが発生しました。", e);
	//		} finally {
	//			SQLUtil.close(pstm);
	//			SQLUtil.close(con);
	//		}
	//	}
	private ArrayList<L1PcInstance>_pcll;
	private final TimeZone tz = TimeZone.getTimeZone(Config.TIME_ZONE);
	private final Calendar cal = Calendar.getInstance(tz);
	private final StringBuilder timer = new StringBuilder().append(cal.get(Calendar.MONTH) + 1).append(cal.get(Calendar.MONTH) + 1).append(cal.get(Calendar.DATE));
	private final int time =  Integer.parseInt(timer.toString());

	private void loadCharacters(){
		if(GetNowTime.GetNowWeek()!=1 || GetNowTime.GetNowHour() != 18 || GetNowTime.GetNowMinute()>15){
			_log.info("今天不是禮拜一...不執行PK歸零與特赦行為。");
			return;
		}
		_log.info("今天是禮拜一...晚上六點...執行PK歸零與特赦行為。");
		_pcll = new ArrayList<L1PcInstance>();
		Connection con = null;
		PreparedStatement pstm = null;
		ResultSet rs = null;
		L1PcInstance pc = null;
		try {
			con = DatabaseFactory.get().getConnection();
			pstm = con.prepareStatement("SELECT * FROM characters WHERE HellTime !=0 || PKcount >0 && ReSetTIme !="+time);
			rs = pstm.executeQuery();
			while(rs.next()){
				pc = new L1PcInstance();
				pc.setAccountName(rs.getString("account_name"));
				pc.setId(rs.getInt("objid"));
				pc.setHellTime((rs.getInt("HellTime")/2));
				pc.setLastPk(null);
				_pcll.add(pc);
			}
		} catch (SQLException e) {
			_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
		} finally {
			SQLUtil.close(rs , pstm , con);
		}
		resetPkCount();
	}

	private void resetPkCount(){
		for(final L1PcInstance pc : _pcll){
			Connection con = null;
			PreparedStatement pstm = null;
			try {
				con = DatabaseFactory.get().getConnection();
				pstm = con.prepareStatement("UPDATE characters SET HellTime = ?, PKcount=?, LastPk=?, ReSetTime=? WHERE objid = ?");
				pstm.setInt(1, pc.getHellTime());
				pstm.setInt(2, 0);
				pstm.setTimestamp(3, null);
				pstm.setInt(4, time);
				pstm.setInt(5, pc.getId());
				pstm.execute();
			} catch (final Exception e) {
				_log.log(Level.SEVERE, "ブックマークの削除でエラーが発生しました。", e);
			} finally {
				SQLUtil.close(pstm);
				SQLUtil.close(con);
			}
		}
	}

	public static boolean LIGHT_IS_OPEN;

	/**更新伺服器燈號*/
	public void UpdateLight(final boolean isOpen){
		if(Config.UPDATE_LIGHT == false){
			return;
		}
		URL myURL1 = null;
		int status1 =0; 
		try {
			if(Config.SERVERCE == 1){
				if(isOpen){
					myURL1 = new URL(Config.LIGHT_1);
				}else{
					myURL1 = new URL(Config.LIGHT_3);
				}
			}else if(Config.SERVERCE == 3){
				if(isOpen){
					myURL1 = new URL(Config.LIGHT_2);
				}else{
					myURL1 = new URL(Config.LIGHT_4);
				}
			}
			HttpURLConnection myURLConnection = (java.net.HttpURLConnection) myURL1.openConnection();
			myURLConnection.setReadTimeout(2000);
			myURLConnection.connect();
			status1 = myURLConnection.getResponseCode();
			switch (status1) {
			case HttpURLConnection.HTTP_GATEWAY_TIMEOUT://504
				System.out.println("連線網址逾時!");
				break;
			case HttpURLConnection.HTTP_FORBIDDEN://403
				System.out.println("連線網址禁止!");
				break;
			case HttpURLConnection.HTTP_INTERNAL_ERROR://500
				System.out.println("連線網址錯誤或不存在!");
				break;
			case HttpURLConnection.HTTP_NOT_FOUND://404
				System.out.println("連線網址不存在!");
				break;
			case HttpURLConnection.HTTP_OK:
				System.out.println("OK!");
				break;
			}
			myURLConnection.disconnect();
		} catch (MalformedURLException e) {
			System.out.println("網址格式錯誤!!!");
			e.printStackTrace();
		} catch (IOException e) {
			System.out.println("連線有問題!!!!!!");
			e.printStackTrace();
		}catch(Exception e){
		}

		LIGHT_IS_OPEN = status1 == HttpURLConnection.HTTP_OK;
	}

	/**開啟驗證伺服器
	 * @throws InterruptedException **/
	private void startFirstServer() throws InterruptedException{ 
		if(Config.SERVERCE !=9999){
			Process pro = null;
			try{
				pro = Runtime.getRuntime().exec("./FirstServer.bat");
				pro.waitFor();
				pro.destroy(); //破壞物件
			}catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**關閉驗證伺服器
	 * @throws InterruptedException **/
	private void stopFirstServer() throws InterruptedException{
		if(Config.SERVERCE !=9999){
			Socket client = null;
			try {
				client = new Socket();
				InetSocketAddress isa = new InetSocketAddress("127.0.0.1", 5092);
				client.connect(isa);
				System.out.println(" 驗證伺服器已經關閉。");
			}catch (Exception e) {
				e.printStackTrace();
			}finally{
				StreamUtil.close(client);
				client = null;
			}
			Process pro = null;
			try{
				Runtime r =Runtime.getRuntime();
				pro = r.exec("./CloseFirstServer.bat");
				pro.waitFor();
				pro.destroy(); //破壞物件
			}catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**開啟三台橋接伺服器
	 * @String ip
	 * @int port**/
	private void startBrigeServer(final String ip ,final int port){
//			while(true){
//				Socket client = null;
//				try {
//					client = new Socket();
//					InetSocketAddress isa = new InetSocketAddress(ip, port);
//					client.setSoTimeout(1000);
//					client.connect(isa);
//					_log.info(ip+" 已連線完成。");
//					break;
//				} catch (Exception e) {
//					_log.info(ip+":"+port+" 連線失敗。");
//					try {
//						Thread.sleep(1000);
//					} catch (InterruptedException e2) {
//						e2.printStackTrace();
//					}
//				}finally{
//					StreamUtil.close(client);
//					client = null;
//				}
//		}
	}
}
